import Raphael from "raphael";

export const initDagreTree = ({ container="", model = null, nodes = [], links = [], connector = 'straight', customRankdir = 'RL' }) => {
    const containerDom = document.querySelector(container);
    const { clientWidth, clientHeight } = containerDom;

    // 创建SVG画布
    const paper = new Raphael(containerDom, clientWidth, clientHeight)
    if (model) {
        // DagreJS图形的宽度和高度
        var graphWidth = model.graph().width;
        var graphHeight = model.graph().height;

        // 计算位移量
        var dx = (clientWidth - graphWidth) / 2;
        var dy = (clientHeight - graphHeight) / 2;

        // 设置viewBox保证内容完全展示
        const svg = paper.setViewBox(-dx, -dy, clientWidth, clientHeight)
    }

    // 创建rect节点
    // const rect = paper.rect(200, 100, 120, 100, 5)
    // const rectBox = rect.getBBox()
    // const { cx, cy, x:Rx, y:Ry, width, height }  = rectBox
    // 文本坐标x=rect.x + rect.width / 2
    // 文本坐标y=rect.y + rect.height / 2
    // let textX = Rx + width / 2, textY = Ry + height / 2;
    // console.log(rectBox, 'text');
    // const text = paper.text(textX, textY, '我是文本内容')
    // text.attr('font-size', 18)
    // text.attr('font-weight', '600')
    // console.log(containerDom, 3333);

    // 绘制元素
    let i = 0
    while (i < nodes.length) {
        // const rect = paper.rect(nodes[i].x, nodes[i].y, nodes[i].width, nodes[i].height, 5)
        // Paint布局（例如SVG和HTML）通常使用标准的盒子模型，元素的x和y位置从左上角开始计算。
        // 然而，DagreJS对位置的计算则略有不同，其x和y是基于元素的中心点进行的。
        // 需要转换元素x和y坐标才能对齐连线
        const rect = paper.rect(nodes[i].x - nodes[i].width / 2, nodes[i].y - nodes[i].height / 2, nodes[i].width, nodes[i].height, 5);
        rect.attr('stroke', Raphael.getColor())
        const rectBox = rect.getBBox()
        const { cx, cy, x:Rx, y:Ry, width, height }  = rectBox
        let textX = Rx + width / 2, textY = Ry + height / 2;
        const text = paper.text(textX, textY, nodes[i].label)
        text.attr({'font-size': 18, 'font-weight': 600 })
        i++;
    }

    // 获取连接线数据
    // const newLinks = linkConnector(connector, links)
    let j = 0;
    while (j < links.length) {
        const parent = nodes.find(el => el.id === links[j].targetId)
        const child = nodes.find(el => el.id === links[j].sourceId)
        // 重新计算起点和终点坐标值
        let startX = child.x-child.width/2, 
            startY = child.y,
            endX = parent.x+parent.width/2,
            endY = parent.y,
            distance = startX - endX; // 计算起始点和结束点坐标距离，曲线控制点需要
            // console.log(distance, 444);

        // RL布局：从右向左布局曲线定位，子节点指向父节点，根节点在最左边
        if (customRankdir === 'RL') {
            // 起点辅助点
            const marker = paper.circle(endX, endY, 5)
            marker.attr('fill', '#10AC84')

            // -1关闭辅助线和控制点，1开启
            if (j == -1) {
                // 控制点1: x1=startX(起始节点)-distance/2(两点距离的一半)
                const c1 = paper.circle(startX-distance/2, startY, 5)
                c1.attr('fill', 'blue')
                // 控制点2：x1=startX(起始节点)+distance/2(两点距离的一半)
                const c2 = paper.circle(endX+distance/2, endY, 5)
                c2.attr('fill', 'red')

                // 辅助线1=c1坐标为终点，起点就是当前节点(startX,startY)
                const s1 = paper.path(`M${startX},${startY} L${startX-distance/2},${startY}`)
                s1.attr({ stroke:'blue', 'stroke-width': 1, 'stroke-dasharray': 10, fill: 'none'})

                // 辅助线2=c2坐标为终点，起点就是当前节点(endX,endY)
                const s2 = paper.path(`M${endX},${endY} L${endX+distance/2},${endY}`)
                s2.attr({ stroke:'red', 'stroke-width': 1, 'stroke-dasharray': 5, fill: 'none' })
            }
            // 自定义曲线
            const path = paper.path(`M${startX},${startY} C${startX-distance/2},${startY} ${endX+distance/2},${endY} ${endX},${endY}`)
            path.attr('stroke', Raphael.getColor())
            path.attr('stroke-width', 3)
        } else {
            // const path = paper.path(`M${startX},${startY} C${startX},${startY} ${endX},${endY} ${endX},${endY}`)
            // path.attr('stroke', Raphael.getColor())
            // path.attr('stroke-width', 3)
        }

        j++;
    }
    // while (j < newLinks.length) {
    //     const path = paper.path(newLinks[j])
    //         path.attr('stroke', Raphael.getColor())
    //         path.attr('stroke-width', 3)
    //     j++;
    // }
    return paper
}

/**
 * 绘制线条模式
 * 当前仅支持 curve曲线  straight直线
 * 
 * @param { String } name 曲线名称 curve || straight
 * @param { Array } links 连接线集合
 */
export const linkConnector = (name = "straight", links = []) => {
    let newLineSet = []
    if (name == void 0) return links
    if (!Array.isArray(links)) {
        new Error('The connection line must be an array of objects')
    }
    if (links.length == 0) return []

    // while (j < links.length) {
    //     const { points } = links[j]
    //     // const path = paper.path(d.join(' '));
    //     // const path = paper.path(`M ${points[0].x} ${points[0].y} L ${points[1].x} ${points[1].y} L ${points[2].x} ${points[2].y}`)
    //     const path = paper.path(`M ${points[0].x} ${points[0].y} Q ${points[1].x} ${points[1].y} ${points[2].x} ${points[2].y}`)
    //         path.attr('stroke', "#10ac84")
    //         path.attr('stroke-width', 3)
    //     j++;
    // }
    
    let i = 0;
    while (i < links.length) {
        const { points } = links[i];
        let _D = '';
        for(let k = 0; k < points.length; k++) {
            // straight 
            if (name === 'straight') {
                if (k === 0) {
                    _D += `M ${points[k].x} ${points[k].y} `
                } else {
                    _D += `L ${points[k].x} ${points[k].y} `
                }
            }
            // curve 
            if (name === 'curve') {
                if (k === 0) {
                    _D += `M ${points[k].x} ${points[k].y} `
                } else if (k === 1){
                    _D += `Q ${points[k].x} ${points[k].y} `
                } else {
                    _D += `${points[k].x} ${points[k].y}`
                }
            }  
        }
        newLineSet.push(_D)
        i++;
    }
    
    return newLineSet
}